using System;
using System.Collections.Generic;
using System.Text;

namespace Pegasus.Data.SqlTypes
{
	/// <summary>
	/// Represents a the SQL Type of TimeStamp
	/// </summary>
	public class SqlTimeStamp
	{
		// Local Instance Values 
		private byte[] m_value = null;

		/// <summary>
		/// Initializes a new instance of the <see cref="T:SqlTimeStamp"/> class.
		/// </summary>
		public SqlTimeStamp()
		{
		}

		/// <summary>
		/// Initializes a new instance of the <see cref="SqlTimeStamp"/> class.
		/// </summary>
		/// <param name="value">The value.</param>
		public SqlTimeStamp( object value )
			: this( (byte[]) value )
		{
		}

		/// <summary>
		/// Initializes a new instance of the <see cref="T:SqlTimeStamp"/> class.
		/// </summary>
		/// <param name="value">The value.</param>
		public SqlTimeStamp( byte[] value )
		{
			m_value = value;
		}

		/// <summary>
		/// Initializes a new instance of the <see cref="SqlTimeStamp"/> class.
		/// </summary>
		/// <param name="value">The value.</param>
		public SqlTimeStamp( UInt64 value )
		{
			m_value = BitConverter.GetBytes( value );
		}

		/// <summary>
		/// Determines whether the specified <see cref="T:System.Object"></see> is equal to the current <see cref="T:System.Object"></see>.
		/// </summary>
		/// <param name="obj">The <see cref="T:System.Object"></see> to compare with the current <see cref="T:System.Object"></see>.</param>
		/// <returns>
		/// true if the specified <see cref="T:System.Object"></see> is equal to the current <see cref="T:System.Object"></see>; otherwise, false.
		/// </returns>
		public override bool Equals( object obj )
		{
			// Is this the same type of object?
			if( !( obj is SqlTimeStamp ) )
			{
				return false;
			}
			
			// Get the bytes.
			byte[] objBytes = ( (SqlTimeStamp) obj ).m_value;

			// If both objects are null (uninitialized) then they are equal.
			if( objBytes == null && m_value == null )
			{
				return true;
			}

			// If the count is not the same then they are not equal.
			int count = m_value.Length;
			if( count == objBytes.Length )
			{
				// Check each byte to see if it's equal.
				for( int x = 0; x < count; x++ )
				{
					if( m_value[ x ] != objBytes[ x ] )
					{
						return false;
					}
				}

				return true;
			}

			return false;
		}

		/// <summary>
		/// Serves as a hash function for a particular type. <see cref="M:System.Object.GetHashCode"></see> is suitable for use in hashing algorithms and data structures like a hash table.
		/// </summary>
		/// <returns>
		/// A hash code for the current <see cref="T:System.Object"></see>.
		/// </returns>
		public override int GetHashCode()
		{
			return base.GetHashCode();
		}

		/// <summary>
		/// Operator ==s the specified a.
		/// </summary>
		/// <param name="a">A.</param>
		/// <param name="b">The b.</param>
		/// <returns></returns>
		public static bool operator == ( SqlTimeStamp a, SqlTimeStamp b )
		{
            if( a.m_value == null )
            {
                return b.m_value == null;
            }

            return b.m_value != null && a.Equals( b );
		}

		/// <summary>
		/// Operator !=s the specified a.
		/// </summary>
		/// <param name="a">A.</param>
		/// <param name="b">The b.</param>
		/// <returns></returns>
		public static bool operator !=( SqlTimeStamp a, SqlTimeStamp b )
		{
            if( a.m_value == null )
            {
                return b.m_value != null;
            }

			return b.m_value == null || !a.Equals( b );
		}

		/// <summary>
		/// Implicit operators the specified value.
		/// </summary>
		/// <param name="value">The value.</param>
		/// <returns></returns>
		public static implicit operator SqlTimeStamp( byte[] value )
		{
			return new SqlTimeStamp( value );
		}

		/// <summary>
		/// Implicit operators the specified stamp.
		/// </summary>
		/// <param name="stamp">The stamp.</param>
		/// <returns></returns>
		public static implicit operator byte[]( SqlTimeStamp stamp )
		{
			return stamp.m_value;
		}

		/// <summary>
		/// Implicit operators the specified stamp.
		/// </summary>
		/// <param name="stamp">The stamp.</param>
		/// <returns>A 32bit integer.</returns>
		public static implicit operator UInt64( SqlTimeStamp stamp )
		{
			return BitConverter.ToUInt64( stamp.m_value, 0 );
		}
	}
}
